package config

import (
	"encoding/json"
	"fmt"
	"github.com/micro/go-micro/v2/config"
	"log"
	"sync"
)

var (
	rw   sync.RWMutex
	conf = &configurator{}
)

type Configurator interface {
	AppConf(conf interface{}) error
}

type configurator struct {
	conf config.Config
	path []string
}

func (c *configurator) AppConf(conf interface{}) error {
	var err error
	v := c.conf.Get(c.path...)
	if v != nil {
		err = v.Scan(&conf)
	} else {
		err = fmt.Errorf("配置不存在")
	}

	return err
}

func (c *configurator) init(conf interface{}, ops Options) error {
	rw.Lock()
	defer rw.Unlock()

	c.conf, _ = config.NewConfig()
	c.path = ops.Path

	if err := c.conf.Load(ops.Sources...); err != nil {
		log.Fatal(err)
		return err
	}

	go func() {
		watcher, err := c.conf.Watch(c.path...)
		if err != nil {
			log.Printf("watcher error:%+v, path:%+v", err, c.path)
			return
		}
		for {
			v, err := watcher.Next()
			if err != nil {
				log.Printf("watcher next error:%+v, path:%+v", err, c.path)
				return
			}

			err = json.Unmarshal(v.Bytes(), &conf)
			if err != nil {
				log.Printf("json unmarshal error:%+v, v:%+v", err, string(v.Bytes()))
				return
			}
			log.Printf("conf:%+v", conf)
		}
	}()

	return nil
}

func Init(config interface{}, opts ...Option) {
	ops := Options{}
	for _, o := range opts {
		o(&ops)
	}

	conf = &configurator{}

	if err := conf.init(config, ops); err != nil {
		log.Fatalf("init error:%+v", err)
	}
}

func Conf() Configurator {
	return conf
}